﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using electricCollimator = OtherDevice.electricCollimatorWrap;    //使用控制库
namespace OtherDevice
{

    [Description("Elec_平行光管")]
    public abstract class Collimator_Base : COM_Base
    {
        public Collimator_Base(string name) : base(name)
        {

        }

        public bool isConnect = false;
        public abstract void Connect(string str_CommPort, ref string Err);
        public abstract bool IsConnect();
        public abstract bool Home(ref string Err, bool IsThread = true);
        public abstract bool MoveDistance(float WDV, ref string Err);
        public abstract bool MoveInf(ref string Err);
        public abstract void SetLight(int ch, int light, ref string Err, string Type);
        public abstract void GetActPos(byte ch, ref string Info);
    }
    [Description("电控平行光管")]

    public class Electric_CollimatorCtrl : Collimator_Base
    {

        public Electric_CollimatorCtrl(string strName) : base(strName)
        {
            controlFrom = new Form_ElectricCollimator();
        }
        public override void InitDeal()
        {
            string Err = "";
            Connect(m_SerialPort.PortName, ref Err);


        }
        public override int InitCom(ComParamter paramter)
        {
            string Err = "";

            try
            {
                Connect(paramter.str_CommPort, /*(uint)paramter.str_BaudRate,*/ ref Err);
                return 0;
            }
            catch (Exception)
            {
                return -1;
            }
        }

        ushort[] usErrorCode = new ushort[20];
        Dictionary<byte, string> m_btAddr = new Dictionary<byte, string>();  //驱动器地址汇总
        Thread m_hThreadHoming = null;		//回零线程句柄
        Thread m_hThreadMonitor = null;		//状态监控线程句柄
        bool m_bMonitor = false;//监控标志
        float[] nEncPos = new float[20];
        StringBuilder pn_MX = new StringBuilder();
        string ProductType;
        public Mutex mutex = new Mutex();

        public override void Connect(string str_CommPort, ref string Err)
        {

            if (!isConnect)
            {
                int[] j_btAddr = new int[20];
                m_btAddr.Clear();
                electricCollimator.ClearCCT();
                try
                {
                    for (byte i = 1; i <= 20; i++)
                    {
                        if (electricCollimator.ManualConnect2(byte.Parse(str_CommPort.Substring(3, str_CommPort.Length - 3)), 19200, i))
                        {
                            m_bMonitor = true;
                            break;
                        }
                    }
                    if (m_bMonitor == false)
                    {
                        for (byte i = 1; i <= 20; i++)
                        {
                            if (electricCollimator.MX_Connect(str_CommPort.Substring(0, str_CommPort.Length), i))//连接串口，Addr地址
                            {
                                break;
                            }
                            else
                            {
                                if (i == 20)
                                {
                                    MessageBox.Show("连接驱动器失败");
                                    return;
                                }
                            }
                        }
                        if (!electricCollimator.MX_IniSlave(Convert.ToByte(20), j_btAddr))//初始化驱动器
                        {
                            MessageBox.Show("初始化失败，未发现驱动器地址");
                            isConnect = false;
                            return;
                        }
                        else
                        {
                            if (j_btAddr.Sum() == 0)
                            {
                                MessageBox.Show("初始化成功，未发现驱动器地址");
                                isConnect = false;
                                return;
                            }
                            else
                            {
                                for (int i = 0; i < 20; i++)
                                {
                                    if (j_btAddr[i] != 0)
                                    {

                                        if (electricCollimator.GetProductType(Convert.ToByte(j_btAddr[i]), pn_MX))
                                        {
                                            ProductType = pn_MX.ToString();
                                            m_btAddr.Add(Convert.ToByte(j_btAddr[i]), ProductType);
                                        }
                                        else
                                        {
                                            MessageBox.Show("获取S系列产品型号异常，请联系市场人员确定产品型号");
                                            isConnect = false;
                                            return;
                                        }
                                    }
                                }
                                m_bMonitor = true;
                            }
                        }
                    }
                    else
                    {
                        for (byte i = 1; i <= 20; i++)
                        {
                            Thread.Sleep(10);
                            if (electricCollimator.GetProductType(i, pn_MX))//GetProductType函数使用当前地址i获得产品型号
                            {
                                ProductType = pn_MX.ToString();
                                m_btAddr.Add(i, ProductType);//将地址和产品型号存入字典m_btAddr
                            }
                        }

                    }
                    if (m_bMonitor)
                    {
                        if (m_btAddr.Count == 0)
                        {
                            MessageBox.Show("连接驱动器均失败，请检查固件版本");
                            isConnect = false;
                            return;
                        }
                        string val = "";
                        foreach (byte item in m_btAddr.Keys)
                        {
                            val += item.ToString() + ",";
                            if (m_btAddr[item].Contains("VT"))
                            {
                                if (!electricCollimator.Enable(item, true))
                                {
                                    MessageBox.Show(item.ToString() + "号V系列平行光管使能失败，如果要使用该支请尝试重新连接驱动");
                                }
                            }
                        }
                        isConnect = true;

                        //启动状态监控线程
                        if (m_hThreadMonitor == null)
                        {
                            m_hThreadMonitor = new Thread(ThreadStatusMonitor);
                            m_hThreadMonitor.Start();
                        }
                    }
                    else
                    {

                    }
                }
                catch (Exception ex)
                {
                    Err = ex.Message + ex.StackTrace;
                    throw;
                }
            }
            else
            {
                try
                {
                    if (m_btAddr.ContainsValue("PL080VT") || m_btAddr.ContainsValue("PL150VT"))//含V系列光管
                    {
                        foreach (byte item in m_btAddr.Keys)
                        {
                            if (m_btAddr[item].Contains("VT"))
                            {
                                if (!electricCollimator.Enable(item, false))
                                {
                                    MessageBox.Show("断开连接前释放电机失败,若不需要使用光管请关控制盒电源");//Failed to release the motor before disconnecting, if you do not need to use the Collimator, please turn off the power of the control box
                                }
                            }
                        }
                        if (electricCollimator.Disconnect())
                        {
                            m_bMonitor = false;
                            isConnect = false;
                            // MessageBox.Show("所有驱动器断开连接");//All drives disconnected
                            return;
                        }
                        else
                        {
                            MessageBox.Show("通讯异常，断开光管连接失败");//The communication is abnormal, and the connection of the light pipe fails to be disconnected.
                            return;
                        }
                    }
                    else
                    {
                        if (electricCollimator.MX_Disconnect())//S系列
                        {
                            m_bMonitor = false;
                            isConnect = false;
                            //  MessageBox.Show("所有驱动器断开连接");//All drives disconnected
                            return;
                        }
                        else
                        {
                            MessageBox.Show("通讯异常，断开光管连接失败");//The communication is abnormal, and the connection of the light pipe fails to be disconnected.
                            return;
                        }

                    }
                }
                catch (Exception ex)
                {
                    Err = ex.Message + ex.StackTrace;
                    throw;
                }




            }
        }



        public override bool IsConnect()
        {
            return electricCollimator.IsConnected();
        }
        public override void GetActPos(byte ch, ref string Info)
        {
            try
            {
                Info = "";
                foreach (byte item in m_btAddr.Keys)
                {
                    if (ch == item)
                    {
                        electricCollimator.GetActPos2(ch, ref nEncPos[ch - 1], m_btAddr[ch]);
                        Info = nEncPos[Convert.ToInt32(ch) - 1].ToString("f2");
                    }
                }
            }
            catch (Exception ex)
            {
            }

        }

        public override bool Home(ref string Err, bool IsThread = true)
        {
            int Count = 0;
            foreach (byte item in m_btAddr.Keys)
            {
                if (m_btAddr[item].Contains("S"))
                {
                    Count++;
                    if (!electricCollimator.MX_Homing(item))
                    {
                        Err = "电机回零失败";
                        return false;
                    }
                }
                else
                {
                    electricCollimator.ClearError(item);//清除告警
                }
            }
            if (Count < m_btAddr.Count)
            {
                //启动X轴回零线程
                if (IsThread)
                {
                    if (m_hThreadHoming == null)
                    {
                        m_hThreadHoming = new Thread(ThreadHoming);
                        m_hThreadHoming.Start();
                        m_hThreadHoming.Join();
                        Thread.Sleep(5000);
                    }
                    else
                    {
                        Err = "回零线程正在运行...";
                    }
                }
                else
                {
                    if (m_hThreadHoming == null)
                    {
                        m_hThreadHoming = new Thread(ThreadHoming);
                        m_hThreadHoming.Start();
                        m_hThreadHoming.Join();
                        MessageBox.Show("回零完成");
                    }
                    else
                    {
                        MessageBox.Show("回零线程正在运行...");
                    }
                }
            }
            return true;
        }



        public override bool MoveDistance(float WDV, ref string Err)
        {
            try
            {
                if (WDV < 0.5f)
                {
                    MessageBox.Show("模拟距离需大于0.5m");
                    return false;
                }
                else
                {
                    foreach (byte item in m_btAddr.Keys)
                    {
                        if (electricCollimator.MoveAbsByFun(item, WDV * 1000, m_btAddr[item]) == false)   //换算模拟位置并运行到模拟位置
                        {
                            Err = "通讯异常，平行光管模拟运动失败！";
                            return false;
                        }
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }

        }

        public override bool MoveInf(ref string Err)
        {
            foreach (byte item in m_btAddr.Keys)
            {
                if (m_btAddr[item].Contains("V"))
                {
                    if ((electricCollimator.iniMotor(item) && electricCollimator.MoveInf(item, m_btAddr[item])) == false)   //设置速度
                    {
                        MessageBox.Show("电动平行光管：通讯异常，模拟无穷远复位运动失败！请断电并重启软件");
                        return false;
                    }
                    Thread.Sleep(10);
                }
            }
            return true;
        }

        public override void SetLight(int ch, int light, ref string Err, string Type = "白光")
        {
            if (ch == 0)
            {
                return;
            }
            if (m_btAddr.Count == 0)
            {
                MessageBox.Show("未找到任何电动平行光管,请确认");
                return;
            }
            bool res = false;
            foreach (var item in m_btAddr)
            {
                if (ch == (int)item.Key)
                {
                    res = true;
                }
            }
            if (!res)
            {
                MessageBox.Show($"未找到通道为{ch}的电动平行光管,请确认");
                return;
            }
            if (Type == "白光")
            {
                bool re = electricCollimator.SetLedPwm((byte)ch, 'w', (ushort)light, m_btAddr[(byte)ch]);//第一个参数是地址，第二个参数是ushort类型的光源亮度值，这个值去控制调节红外光光源，STA系统光管第三个参数传入m_btAddr[item]
                if (!re)
                {
                    MessageBox.Show("电动平行光管：设置白色光源亮度失败");
                }
                else
                {
                    Err = $"设置白光亮度{light}成功";
                }
            }
            else /*if (Type == "红外")*/
            {
                bool re = electricCollimator.SetLedPwm((byte)ch, '9', (ushort)light, m_btAddr[(byte)ch]);//第一个参数是地址，第二个参数是ushort类型的光源亮度值，这个值去控制调节红外光光源，STA系统光管第三个参数传入m_btAddr[item]
                if (!re)
                {
                    MessageBox.Show("电动平行光管：设置红外光源亮度失败");
                }
                else
                {
                    Err = $"设置红外光亮度{light}成功";
                }
            }
        }
        public void ThreadHoming()	//回零线程
        {
            bool bEnabled = true;
            foreach (byte item in m_btAddr.Keys)
            {
                if (m_btAddr[item].Contains("V"))
                {
                    if (electricCollimator.IsEnabled(item, ref bEnabled))    //先判断电机是否使能
                    {
                        if (bEnabled == false)  //未使能
                        {
                            MessageBox.Show("电机未使能，回零失败！请断开驱动重连驱动后再试");
                            m_hThreadHoming = null; //将回零线程句柄清除
                            return;
                        }
                    }
                    else
                    {
                        MessageBox.Show("通讯异常，回零失败！");
                        m_hThreadHoming = null; //将回零线程句柄清除
                        return;
                    }
                }

            }

            //开始回零过程。。。
            int Count = 0;

            foreach (byte item in m_btAddr.Keys)
            {
                if (m_btAddr[item].Contains("V"))
                {
                    electricCollimator.SoftLanding(item, 10, 1, 800, false); //函数不等待完成
                    Count++;
                }

            }
            //等待停止

            bool[] Postest = new bool[Count];
            int PostestCount = 0;
            int nTimeout = 0;   //2秒超时退出
            //查询等待是否运动到负极限
            while (true)
            {
                PostestCount = 0;
                bool bInPos = true; //到位标志，true=到位
                foreach (byte item in m_btAddr.Keys)
                {
                    if (m_btAddr[item].Contains("V"))
                    {
                        electricCollimator.IsInPosition(item, ref Postest[PostestCount]);
                        PostestCount++;
                    }

                }
                PostestCount = 0;
                foreach (byte item in m_btAddr.Keys)
                {
                    if (m_btAddr[item].Contains("V"))
                    {
                        bInPos = bInPos && Postest[PostestCount];
                        PostestCount++;
                    }

                }
                //运动到负极限
                if (bInPos)
                {
                    //Invoke((Action)(() => { textBoxFault.Text = "到位！"; }));
                    break;
                }

                Thread.Sleep(10);
                if ((nTimeout++) == 1000) //
                {
                    MessageBox.Show("平行光管回零时，软着陆失败！请重启软件");
                    m_hThreadHoming = null; //将回零线程句柄清除
                    return;
                }
            }

            //轴到达负极限后，切换回位置模式，在往正方向找编码器的零位(Z信号，或称Index信号)

            //设置为位置模式
            foreach (byte item in m_btAddr.Keys)
            {
                if (m_btAddr[item].Contains("V"))
                {
                    electricCollimator.SetServoMode(item, 0);
                }

            }
            Thread.Sleep(10);

            //往正方向找Index， 函数不等待完成
            foreach (byte item in m_btAddr.Keys)
            {
                if (m_btAddr[item].Contains("V"))
                {//btAddr为驱动器地址，usVel为搜索速度，usAcc为搜索加速度，dir为搜索方向,0为正方向，1为负方向
                    electricCollimator.FindIndex(item, 10, 100, 0, false);
                }
            }
            //查询等待是否完成
            nTimeout = 0;
            bool[] Postest_twice = new bool[Count];
            while (true)
            {
                PostestCount = 0;
                bool bInPos = true; //到位标志，true=到位
                foreach (byte item in m_btAddr.Keys)
                {
                    if (m_btAddr[item].Contains("V"))
                    {
                        electricCollimator.IsInPosition(item, ref Postest_twice[PostestCount]); //函数不等待完成
                        PostestCount++;
                    }

                }
                PostestCount = 0;
                foreach (byte item in m_btAddr.Keys)
                {
                    if (m_btAddr[item].Contains("V"))
                    {
                        bInPos = bInPos && Postest_twice[PostestCount];
                        PostestCount++;
                    }

                }
                //轴运动到负极限
                if (bInPos)
                {
                    break;
                }

                Thread.Sleep(10);
                if ((nTimeout++) == 500) //5秒超时退出
                {
                    MessageBox.Show("平行光管回零失败！请重启软件");

                    m_hThreadHoming = null; //将回零线程句柄清除
                    return;
                }
            }
            //Invoke((Action)(() => { textBoxFault.Text = "回零完成！"; }));

            m_hThreadHoming = null; //将回零线程句柄清除
            //复位到无穷远
            foreach (byte item in m_btAddr.Keys)
            {
                if (m_btAddr[item].Contains("V"))
                {
                    if ((electricCollimator.iniMotor(item) && electricCollimator.MoveInf(item, m_btAddr[item])) == false)   //设置速度
                    {
                        MessageBox.Show("平行光管通讯异常，模拟无穷远复位运动失败！！请重启软件");
                        return;
                    }
                    Thread.Sleep(10);
                }
            }
            return;
        }
        public void ThreadStatusMonitor(object lpParameter)	//状态监控线程
        {
            while (m_bMonitor)
            {
                Thread.Sleep(500);

                //报警状态
                foreach (byte item in m_btAddr.Keys)
                {
                    if (m_btAddr[item].Contains("V"))
                    {
                        if (electricCollimator.GetErrorCode(item, ref usErrorCode[item - 1]))
                        {
                            switch (usErrorCode[item - 1])
                            {
                                case 1:
                                    if (!electricCollimator.Enable(item, true))
                                    {
                                        MessageBox.Show(item.ToString() + "号未使能且重新使能失败");
                                    }
                                    break;
                                case 2:
                                    MessageBox.Show(item.ToString() + "号正在运动，请复位");
                                    break;
                                case 3:
                                    MessageBox.Show(item.ToString() + "号跟随误差报警，请复位");
                                    break;
                                case 4:
                                    MessageBox.Show(item.ToString() + "号跟随误差超限，请复位");
                                    break;
                                case 5:
                                    MessageBox.Show(item.ToString() + "号驱动电流稍大，请复位");
                                    break;
                                case 6:
                                    MessageBox.Show(item.ToString() + "号过热，请复位");
                                    break;
                                case 7:
                                    MessageBox.Show(item.ToString() + "号出现操作不允许，请复位");
                                    break;
                                case 8:
                                    MessageBox.Show(item.ToString() + "号序列号错误，请复位");
                                    break;
                                case 9:
                                    MessageBox.Show(item.ToString() + "号功率元件故障，请复位");
                                    break;
                                case 10:
                                    MessageBox.Show(item.ToString() + "号控制方式冲突，请复位");
                                    break;
                                case 11:
                                    MessageBox.Show(item.ToString() + "号伺服模式错误，请复位");
                                    break;
                                    //default:
                                    //    break;
                            }
                        }
                    }
                    else
                    {
                        mutex.WaitOne();
                        if (electricCollimator.GetStatus(item, ref usErrorCode[item - 1], m_btAddr[item]))   //获取报警代码，放入usErrorCode中
                        {
                            switch (usErrorCode[item - 1])
                            {
                                case 4:
                                    MessageBox.Show(item.ToString() + "零位不确定过流或过热");
                                    break;
                                case 6:		//2正常                   
                                    MessageBox.Show(item.ToString() + "零位确定过流或过热");
                                    break;
                                case 8:
                                    MessageBox.Show(item.ToString() + "零位不确定软件限位或光电开关限位");
                                    break;
                                case 10:
                                    MessageBox.Show(item.ToString() + "零位确定软件限位或光电开关限位");
                                    break;
                            }
                        }
                        mutex.ReleaseMutex();
                    }
                    mutex.WaitOne();
                    mutex.ReleaseMutex();
                }
            }
            m_hThreadMonitor = null;
        }
    }
}